package GDoc::Listing;

use Moose;
use Carp 'croak';
use Net::Amazon::S3;
use DateTime::Format::Strptime;
use Data::Dumper;

use GDoc::Const 'SITE_CONF';
use GDoc::Document;
use GDoc::AWS '$AWS_ACCESS_KEY_ID', '$AWS_SECRET_KEY';


our @CONF;
BEGIN { 
    my $tmp = do {
        local $/;
        open my $fh, '<', SITE_CONF or die "Can't open " . SITE_CONF . " $!";
        YAML::XS::Load( <$fh> );
    };

    @CONF = @{ $tmp };
}

has 'type'          => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1
                       );

has 'name'          => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1 
                       );

has 'output'        => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1
                       );

has 'index'         => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1 
                       );

has 'year_output'   => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 0 
                       );

has 'year_index'    => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 0
                       );

has 'congress_output'   => ( is        => 'ro',
                             isa       => 'Str',
                             required  => 0 
                           );

has 'congress_index'    => ( is        => 'ro',
                             isa       => 'Str',
                             required  => 0
                           );

has 'prefix'        => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1
                       );

has 'desc'          => ( is        => 'ro',
                         isa       => 'Str',
                         required  => 1
                       );

has 'documents'     => ( is        => 'rw',
                         isa       => 'ArrayRef',
                         init_arg  => undef
                       );

has 'crumbs'        => ( is        => 'rw',
                         isa       => 'ArrayRef',
                         init_arg  => undef
                       );

has 'parent_type'   => ( is        => 'rw',
                         isa       => 'Str',
                         default   => '',
                         required  => 0
                       );

has 'syndicate'     => ( is        => 'rw',
                         isa       => 'HashRef',
                         required  => 0
                       );


has 'syndicate_link' => ( is         => 'rw',
                          isa        => 'Str',
                          default    => '',
                          required   => 0
                        );

has 'agency'       => ( is         => 'rw',
                        isa        => 'Item',
                        required   => 0,
                        default    => ''
                      );

sub BUILD { 
    my $self = shift;
    unless( exists $self->{documents} ) { 
        $self->populate_documents;
    }

    my @parts = grep { length } split '/', $self->index;
    my @crumbs;

    my $path;
    foreach my $part( @parts ) { 
        $path .= '/' . $part;

        if ( ( $part =~ /^\d{4}$/ ) and ( $self->parent_type eq 'listing_yearly' ) ) { 
            push @crumbs, { path => $path, name => $part }
        } elsif ( ( $part =~ /^\d{3}$/ ) and ( $self->parent_type eq 'listing_congressional' ) ) { 
            push @crumbs, { path => $path, name => $part . 'th Congress' }     ### FIX: proper ordinal detection here
        } else { 
            my ( $thing ) = grep { $_->{index} eq $path } @CONF;
            push @crumbs, { path => $path, name => ( $thing->{name} or 'US' ) };
        }
    }


    # throw away all but the last three
    @crumbs = @crumbs[ -3 .. -1 ];

    $self->crumbs( \@crumbs );

    
}


sub years { 
    my $self = shift;

    unless ( $self->type eq 'listing_yearly' ) { 
        die q{can't get year list on listing of type } . $self->type;
    }

    my %seen;
    my $prefix = $self->prefix;
    $prefix =~ m{/(?<part>[\w-]+)$};
    my $part = $+{part};
    my @years = grep { !$seen{$_}++ } map { 
        my $ident = $_->identifier;
        $ident =~ /^$part-(?<year>\d{4})/;

        unless ( $+{year} ) { 
            die "Can't find year in ident [$ident] prefix [$part]";
        }

        $+{year};
    } @{ $self->documents };

    return @years;
}


sub congresses {
    my $self = shift;
    
    unless ( $self->type eq 'listing_congressional' ) { 
        die q{Can't get congress list on listing of type } . $self->type;
    }

    my %seen;
    my $prefix = $self->prefix;
    $prefix =~ m{/(?<part>[\w-]+)$};
    my $part = $+{part};
    my @congs = grep { !$seen{$_}++ } map { 
        my $ident = $_->identifier;
        $ident =~ /^$part-(?<cong>\d{3})/; 

        unless ( $+{cong} ) { 
            die "Can't find congress in ident [$ident] prefix [$part]";
        }

        $+{cong};
    } grep { 
        $_->identifier !~ /000/      # some of these are messed up
    } @{ $self->documents };

    return @congs;
}

my %DOC_CACHE;
sub populate_documents { 
    my $self = shift;

    if ( my $res = $DOC_CACHE{$self->prefix} ) { 
        return $self->{documents} = $res;
    }

    my $s3 = Net::Amazon::S3->new( aws_access_key_id => $AWS_ACCESS_KEY_ID,
                                   aws_secret_access_key => $AWS_SECRET_KEY,
                                   retry => 1
                                 );

    my $strp = DateTime::Format::Strptime->new( pattern => q{%a, %d %b %Y %T %Z}, on_error => "croak" );

    my $bkt = $s3->bucket( 'docs.govdoc.org' );
    my $res = $bkt->list_all( { prefix => $self->prefix } );

    $self->{documents} = $DOC_CACHE{$self->prefix} = [ map { 
        my $cfg = $bkt->head_key( $_->{key} );

        GDoc::Document->new( key          => $_->{key},
                             type         => $cfg->{'content-type'},
                             size         => $cfg->{'content-length'},
                             description  => $cfg->{'x-amz-meta-description'},
                             identifier   => $cfg->{'x-amz-meta-identifier'},
                             date         => $strp->parse_datetime( $cfg->{'last-modified'} )
                           )
    } @{ $res->{keys} } ];
}

1;


